// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. See the AUTHORS file for names of contributors.

#ifndef STORAGE_LEVELDB_INCLUDE_DB_H_
#define STORAGE_LEVELDB_INCLUDE_DB_H_

#include <cstdint>
#include <cstdio>

#include "leveldb/export.h"
#include "leveldb/iterator.h"
#include "leveldb/options.h"

namespace leveldb
{

    // Update CMakeLists.txt if you change these
    static const int kMajorVersion = 1;
    static const int kMinorVersion = 23;

    struct Options;
    struct ReadOptions;
    struct WriteOptions;
    class WriteBatch;

    // Abstract handle to particular state of a DB.
    // A Snapshot is an immutable object and can therefore be safely
    // accessed from multiple threads without any external synchronization.
    class LEVELDB_EXPORT Snapshot
    {
    protected:
        virtual ~Snapshot();
    };

    // A range of keys
    struct LEVELDB_EXPORT Range
    {
        Range() = default;
        Range(const Slice &s, const Slice &l) : start(s), limit(l) {}

        Slice start; // Included in the range
        Slice limit; // Not included in the range
    };

    // A DB is a persistent ordered map from keys to values.
    // A DB is safe for concurrent access from multiple threads without
    // any external synchronization.
    /* 一个DB是一个key-value的持久化有序map */
    /* DB 在多线程下可以安全的并发访问，并且不需要加任何额外的同步手段。 */
    class LEVELDB_EXPORT DB
    {
    public:
        // Open the database with the specified "name".
        // Stores a pointer to a heap-allocated database in *dbptr and returns
        // OK on success.
        // Stores nullptr in *dbptr and returns a non-OK status on error.
        // Caller should delete *dbptr when it is no longer needed.
        /*  
            fcn :  DB::Open()
            以指定的name打开数据库。
            将一个指向在堆内存中申请的db指针存储在dbptr中，在成功的时候返回OK。
            当发生错误的时候，将一个nullptr存储在dbptr中, 并返回一个non-OK的错误。
            调用者需要在不适用dbptr时将其进行删除。
        */
        static Status Open(const Options &options, const std::string &name,
                           DB **dbptr);

        /* 默认构造函数 */
        DB() = default;

        /* 禁止拷贝构造函数和赋值操作 */
        DB(const DB &) = delete;
        DB &operator=(const DB &) = delete;

        /* 析构函数，声明为虚函数。因为这里的DB类通常是作为基类存在，这样可以使得子类能够正确调用子类的析构函数。 */
        /* 详见：Effective C++ 条款7：为多态基类声明virtual析构函数 */
        virtual ~DB();

        // Set the database entry for "key" to "value".  Returns OK on success,
        // and a non-OK status on error.
        // Note: consider setting options.sync = true.
        /* 
            fcn :  DB::Put()
            纯虚函数，子类需要自己实现相应的副本。将k-v键值对存储到db中，成功返回ok，失败返回non-OK。
            note: 需要考虑设置选项 options.sync = true.
        */
        virtual Status Put(const WriteOptions &options, const Slice &key,
                           const Slice &value) = 0;

        // Remove the database entry (if any) for "key".  Returns OK on
        // success, and a non-OK status on error.  It is not an error if "key"
        // did not exist in the database.
        // Note: consider setting options.sync = true.
        /* 
            fcn :  DB::Delete()
            纯虚函数，子类需要自己实现相应的副本。删除数据库中"key"对应的键值对(如果有)，成功返回ok，失败返回non-OK。
            db中未含有"key"并不是一种错误。
            note: 需要考虑设置选项 options.sync = true.
        */
        virtual Status Delete(const WriteOptions &options, const Slice &key) = 0;

        // Apply the specified updates to the database.
        // Returns OK on success, non-OK on failure.
        // Note: consider setting options.sync = true.
        /* 
            fcn :  DB::Write()
            纯虚函数，子类需要自己实现相应的副本。将指定的更新写入数据库。
            note: 需要考虑设置选项 options.sync = true.
        */
        virtual Status Write(const WriteOptions &options, WriteBatch *updates) = 0;

        // If the database contains an entry for "key" store the
        // corresponding value in *value and return OK.
        //
        // If there is no entry for "key" leave *value unchanged and return
        // a status for which Status::IsNotFound() returns true.
        //
        // May return some other Status on an error.
        /* 
            fcn :  DB::Get()
            纯虚函数，子类需要自己实现相应的副本。如果db中含有key对应的value，则将值保存在value中并返回ok，如果没有key，则不会修改value并返回Status::IsNotFound()。
            note: 需要考虑设置选项 options.sync = true.
        */
        virtual Status Get(const ReadOptions &options, const Slice &key,
                           std::string *value) = 0;

        // Return a heap-allocated iterator over the contents of the database.
        // The result of NewIterator() is initially invalid (caller must
        // call one of the Seek methods on the iterator before using it).
        //
        // Caller should delete the iterator when it is no longer needed.
        // The returned iterator should be deleted before this db is deleted.
        virtual Iterator *NewIterator(const ReadOptions &options) = 0;

        // Return a handle to the current DB state.  Iterators created with
        // this handle will all observe a stable snapshot of the current DB
        // state.  The caller must call ReleaseSnapshot(result) when the
        // snapshot is no longer needed.
        virtual const Snapshot *GetSnapshot() = 0;

        // Release a previously acquired snapshot.  The caller must not
        // use "snapshot" after this call.
        virtual void ReleaseSnapshot(const Snapshot *snapshot) = 0;

        // DB implementations can export properties about their state
        // via this method.  If "property" is a valid property understood by this
        // DB implementation, fills "*value" with its current value and returns
        // true.  Otherwise returns false.
        //
        //
        // Valid property names include:
        //
        //  "leveldb.num-files-at-level<N>" - return the number of files at level <N>,
        //     where <N> is an ASCII representation of a level number (e.g. "0").
        //  "leveldb.stats" - returns a multi-line string that describes statistics
        //     about the internal operation of the DB.
        //  "leveldb.sstables" - returns a multi-line string that describes all
        //     of the sstables that make up the db contents.
        //  "leveldb.approximate-memory-usage" - returns the approximate number of
        //     bytes of memory in use by the DB.
        virtual bool GetProperty(const Slice &property, std::string *value) = 0;

        // For each i in [0,n-1], store in "sizes[i]", the approximate
        // file system space used by keys in "[range[i].start .. range[i].limit)".
        //
        // Note that the returned sizes measure file system space usage, so
        // if the user data compresses by a factor of ten, the returned
        // sizes will be one-tenth the size of the corresponding user data size.
        //
        // The results may not include the sizes of recently written data.
        virtual void GetApproximateSizes(const Range *range, int n,
                                         uint64_t *sizes) = 0;

        // Compact the underlying storage for the key range [*begin,*end].
        // In particular, deleted and overwritten versions are discarded,
        // and the data is rearranged to reduce the cost of operations
        // needed to access the data.  This operation should typically only
        // be invoked by users who understand the underlying implementation.
        //
        // begin==nullptr is treated as a key before all keys in the database.
        // end==nullptr is treated as a key after all keys in the database.
        // Therefore the following call will compact the entire database:
        //    db->CompactRange(nullptr, nullptr);
        virtual void CompactRange(const Slice *begin, const Slice *end) = 0;
    };

    // Destroy the contents of the specified database.
    // Be very careful using this method.
    //
    // Note: For backwards compatibility, if DestroyDB is unable to list the
    // database files, Status::OK() will still be returned masking this failure.
    LEVELDB_EXPORT Status DestroyDB(const std::string &name,
                                    const Options &options);

    // If a DB cannot be opened, you may attempt to call this method to
    // resurrect as much of the contents of the database as possible.
    // Some data may be lost, so be careful when calling this function
    // on a database that contains important information.
    LEVELDB_EXPORT Status RepairDB(const std::string &dbname,
                                   const Options &options);

} // namespace leveldb

#endif // STORAGE_LEVELDB_INCLUDE_DB_H_
